﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;

using System.Linq;
using System.Text;
using System.Windows.Forms;
using Encoder = System.Drawing.Imaging.Encoder;

namespace UgaScreenShotMaker
{
    

    public partial class MainForm : Form
    {
        #region constants and variables

        private const int CornerSize = 5;
        private const string LabelMainText = "Screenshot Area";
        private const int FormMinWidth = 50;
        private const int FormMinHeight = 50;
        private const int ResizeTimerInterval = 2;
        private const double FormOpacity = 0.6;

        private Brush bodyBrush = Brushes.LimeGreen;
        private Brush frameBrush = Brushes.Green;
        
        private SizeF _labelMainSize;
        private Font _labelMainFont;

        private FormSides _lastMousePlace;
        private int _lastMouseX = 0;
        private int _lastMouseY = 0;
        private bool _isMouseOnButton;

        private Timer _resizeTimer;
        private KeysHook _keysHook;

        #endregion

        public MainForm()
        {
            InitializeComponent();
            this.Icon = Properties.Resources.usm;
        }
    
        #region Form

        private void MainForm_Load(object sender, EventArgs e)
        {
            this.Paint += new PaintEventHandler(MainForm_Paint);
            this.Opacity = FormOpacity;
            _resizeTimer = new Timer();
            _resizeTimer.Interval = ResizeTimerInterval;
            _resizeTimer.Tick += new EventHandler(resizeTimer_Tick);

            _keysHook = new KeysHook();
            _keysHook.OnKeyDown += new EventHandler<EventArgs<Keys>>(keysHook_OnKeyDown);

            _labelMainFont = new Font("Tahoma", 22);
            _labelMainSize = this.CreateGraphics().MeasureString(LabelMainText, _labelMainFont);
        }

        private void MainForm_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.FillRectangle(frameBrush, 0, 0, this.Width, this.Height);
            e.Graphics.FillRectangle(bodyBrush, CornerSize, CornerSize, this.Width - (CornerSize * 2), this.Height - (CornerSize * 2));
            int ty = this.Height / 2 - (int)(_labelMainSize.Height /2);
            int tx = this.Width / 2 - (int)(_labelMainSize.Width / 2);
            e.Graphics.DrawString(LabelMainText, _labelMainFont, Brushes.White, tx, ty);
        }

        private void MainForm_MouseMove(object sender, MouseEventArgs e)
        {
            if (_lastMousePlace == FormSides.None)
            {
                this.Cursor = GetCursor(GetMouseSide(Cursor.Position.X, Cursor.Position.Y));
            }

        }

        private void MainForm_MouseDown(object sender, MouseEventArgs e)
        {
            if (WindowState == FormWindowState.Normal)
            {
                if (e.Button == MouseButtons.Left)
                {
                    _lastMouseX = Cursor.Position.X;
                    _lastMouseY = Cursor.Position.Y;
                    _lastMousePlace = GetMouseSide(_lastMouseX, _lastMouseY);
                    _resizeTimer.Enabled = true;
                    this.Cursor = GetCursor(_lastMousePlace);
                }
            }
        }

        private void MainForm_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                _resizeTimer.Enabled = false;
                _lastMousePlace = FormSides.None;
            }
        }

        private void MainForm_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                Maximize();
            }
            else if (e.Button == MouseButtons.Middle)
            {
                Minimize();
            }
        }

        private void MainForm_VisibleChanged(object sender, EventArgs e)
        {
            if (this.Visible)
            {
                _keysHook.Unhook();
            }
            else
            {
                _keysHook.Hook();
            }
        }

        protected override void WndProc(ref Message message)
        {
            if (message.Msg == SingleInstance.WM_SHOWFIRSTINSTANCE)
            {
                this.Visible = true;
            }
            base.WndProc(ref message);
        }

        #endregion

        #region links

        private void link_MouseHover(object sender, EventArgs e)
        {
            this.Cursor = Cursors.Arrow;
            _isMouseOnButton = true;
        }

        private void link_MouseLeave(object sender, EventArgs e)
        {
            _isMouseOnButton = false;
        }

        private void linkToFile_Clicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            MakeScreenShotToFile();
            this.Refresh();
        }

        private void linkToClipboard_Clicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            MakeScreenShotToCliboard();
            this.Refresh();
        }

        private void linkExit_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            this.Close();
        }

        private void linkPrintScreen_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            this.Visible = false;
        }

        private void linkMaximize_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Maximize();
        }

        private void linkMinimize_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Minimize();
        }

        #endregion 

        #region methods

        private void keysHook_OnKeyDown(object sender, EventArgs<Keys> e)
        {
            if (e.Value == Keys.PrintScreen)
            {
                this.Visible = true;
            }
        }

        private void resizeTimer_Tick(object sender, EventArgs e)
        {
            int nx = Cursor.Position.X;
            int ny = Cursor.Position.Y;


            int dx = nx - _lastMouseX;
            int dy = ny - _lastMouseY;

            int newWidth = this.Width;
            int newHeight = this.Height;

            Point newLocation = this.Location;

            switch (_lastMousePlace)
            {
                case FormSides.Body:
                    newLocation = new Point(this.Location.X + dx, this.Location.Y + dy);
                    break;

                case FormSides.Bottom:
                    newHeight = this.Height + dy;
                    break;

                case FormSides.BottomLeft:
                    newWidth = this.Width - dx;
                    newHeight = this.Height + dy;
                    newLocation = new Point(this.Location.X + dx, this.Location.Y);
                    break;
                case FormSides.BottomRight:
                    newHeight = this.Height + dy;
                    newWidth = this.Width + dx;
                    break;

                case FormSides.Left:
                    newWidth = this.Width - dx;
                    newLocation = new Point(this.Location.X + dx, this.Location.Y);
                    break;

                case FormSides.Right:
                    newWidth = this.Width + dx;
                    break;

                case FormSides.Top:
                    newHeight = this.Height - dy;
                    newLocation = new Point(this.Location.X, this.Location.Y + dy);
                    break;

                case FormSides.TopLeft:
                    newHeight = this.Height - dy;
                    newWidth = this.Width - dx;
                    newLocation = new Point(this.Location.X + dx, this.Location.Y + dy);
                    break;

                case FormSides.TopRight:
                    newHeight = this.Height - dy;
                    newWidth = this.Width + dx;
                    newLocation = new Point(this.Location.X, this.Location.Y + dy);
                    break;
            }

            if (newHeight > FormMinHeight)
            {
                this.Height = newHeight;
            }
            if (newWidth > FormMinWidth)
            {
                this.Width = newWidth;
            }
            this.Location = newLocation;
            _lastMouseX = nx;
            _lastMouseY = ny;
        }

        private void Minimize()
        {
            if (this.WindowState != FormWindowState.Minimized)
            {
                this.WindowState = FormWindowState.Minimized;
            }
            else if (this.WindowState != FormWindowState.Normal)
            {
                this.WindowState = FormWindowState.Normal;
            }
        }

        private void Maximize()
        {
            if (this.WindowState != FormWindowState.Maximized)
            {
                this.WindowState = FormWindowState.Maximized;
            }
            else if (this.WindowState != FormWindowState.Normal)
            {
                this.WindowState = FormWindowState.Normal;
            }
        }

        private FormSides GetMouseSide(int x, int y)
        {
            if (_isMouseOnButton)
            {
                return FormSides.None;
            }
            var formRect = new Rectangle(this.Location.X, this.Location.Y, this.Width, this.Height);
            
            if (x > formRect.Left && x < formRect.Left + CornerSize)
            {
                if (y > formRect.Top && y < formRect.Top + CornerSize)
                {
                    return FormSides.TopLeft;
                }
                if (y < formRect.Bottom && y > formRect.Bottom - CornerSize)
                {
                    return FormSides.BottomLeft;
                }
                return FormSides.Left;
            }

            if (x > formRect.Right - CornerSize && x < formRect.Right)
            {
                if (y > formRect.Top && y < formRect.Top + CornerSize)
                {
                    return FormSides.TopRight;
                }
                if (y < formRect.Bottom && y > formRect.Bottom - CornerSize)
                {
                    return FormSides.BottomRight;
                }
                return FormSides.Right;
            }

            if (x > formRect.Left && x < formRect.Right)
            {
                if (y > formRect.Top && y < formRect.Top + CornerSize)
                {
                    return FormSides.Top;
                }
                if (y < formRect.Bottom && y > formRect.Bottom - CornerSize)
                {
                    return FormSides.Bottom;
                }

                if (y > formRect.Top && y < formRect.Bottom)
                {
                    return FormSides.Body;
                }
            }

            return FormSides.None;
        }

        private Cursor GetCursor(FormSides sideCorner)
        {
            switch (sideCorner)
            {
                case FormSides.Top:
                case FormSides.Bottom:
                    return Cursors.SizeNS;
                case FormSides.Left:
                case FormSides.Right:
                    return Cursors.SizeWE;
                case FormSides.BottomLeft:
                case FormSides.TopRight:
                    return Cursors.SizeNESW;
                case FormSides.TopLeft:
                case FormSides.BottomRight:
                    return Cursors.SizeNWSE;
                case FormSides.Body:
                    return Cursors.SizeAll;
            }
            return Cursors.Arrow;
        }

        private Bitmap MakeScreenShot()
        {
            var bounds = this.Bounds;
            this.Visible = false;

            Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb);
            using (Graphics g = Graphics.FromImage(bitmap))
            {
                g.CopyFromScreen(bounds.Location, new Point(0, 0), bounds.Size);
            }
            this.Visible = true;
            return bitmap;
        }

        private void MakeScreenShotToCliboard()
        {
            Bitmap img = MakeScreenShot();
            Clipboard.SetImage(img);
        }

        private void MakeScreenShotToFile()
        {
            Bitmap img = MakeScreenShot();
            if (saveFileDialog1.FileName != string.Empty)
            {
                string ext = System.IO.Path.GetExtension(saveFileDialog1.FileName);
                saveFileDialog1.FileName = saveFileDialog1.FileName.Replace(ext, "");
            }
            if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                switch (saveFileDialog1.FilterIndex)
                {
                    case 0: img.Save(saveFileDialog1.FileName, ImageFormat.Jpeg); break;
                    case 1: img.Save(saveFileDialog1.FileName, ImageFormat.Png); break;
                }
            }
        }

        
        #endregion

     
    }
}    
